/**
 * 
 */
package org.xserver;

import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.ResourceBundle;

/**
 * @author jkonopka
 * 
 */
public final class Messages {

	/**
	 * 
	 */
	private Messages() {
	}

	/**
	 * the name to the used resource bundle.
	 */
	private static final String RESOURCE_BUNDLE_NAME = "messages";

	/**
	 * the instance of {@link Messages}
	 */
	private static final Messages INSTANCE = new Messages();

	/**
	 * the cached {@link Map} with the value to caching.
	 */
	private final Map<String, String> CACHE = new HashMap<String, String>();

	/**
	 * @return instance of {@link Messages}
	 */
	public static Messages getInstance() {
		return INSTANCE;
	}

	/**
	 * @return {@link Messages#CACHE}
	 */
	public static Map<String, String> getCache() {
		return getInstance().CACHE;
	}

	/**
	 * get the value from the {@link Messages#CACHE}.
	 * 
	 * @param key Key to Cache value
	 * @return value
	 */
	private String getCacheValue(final String key) {
		return getCache().get(key);
	}

	/**
	 * add value to the {@link Messages#CACHE}.
	 * 
	 * @param key Key
	 * @param value Value
	 */
	private void addCacheValue(final String key, final String value) {
		getCache().put(key, value);
	}

	/**
	 * get the value from Resourcebundle and put the value into the
	 * {@link Messages#CACHE}.
	 * 
	 * @param key Key
	 * @return value from resource bundle
	 */
	private String getResourceBundleValue(final String key) {
		final String value = getResourceBundle().getString(key);
		addCacheValue(key, value);
		return value;
	}

	/**
	 * @return {@link ResourceBundle}
	 * @throws NullPointerException - if baseName or locale is null<br>
	 *             {@link MissingResourceException} - if no resource bundle for
	 *             the specified base name can be found
	 */
	private static ResourceBundle getResourceBundle() {
		return ResourceBundle.getBundle(RESOURCE_BUNDLE_NAME, Locale.getDefault());
	}

	/**
	 * get the value by key.<br>
	 * if the value was found in resource bundle then put the value in to the
	 * {@link Messages#CACHE}.<br>
	 * 
	 * @param key key for query resource bundle
	 * @return the value which was found
	 * @throws NullPointerException - if baseName or locale is null<br>
	 *             {@link MissingResourceException} - if no resource bundle for
	 *             the specified base name can be found
	 * @exception NullPointerException if <code>key</code> is <code>null</code>
	 * @exception MissingResourceException if no object for the given key can be
	 *                found
	 * @exception ClassCastException if the object found for the given key is
	 *                not a string
	 */
	public static String getValue(final String key) {
		String value = getInstance().getCacheValue(key);
		if (value == null) {
			value = getInstance().getResourceBundleValue(key);
		}
		return value;
	}

	/**
	 * @param key key
	 * @param params params for {@link String#format(String, Object...)} arguments
	 * @return value
	 */
	public static String getValue(final String key, final Object... params) {
		return String.format(getValue(key), params);
	}
}
